package com.fac.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fac.constant.EquipmentStatus;
import com.fac.constant.RepairStatus;
import com.fac.constant.ExceptionConstant;
import com.fac.dto.*;
import com.fac.entity.Equipment;
import com.fac.entity.RepairOrder;
import com.fac.entity.Users;
import com.fac.exception.BusinessException;
import com.fac.mapper.EquipmentMapper;
import com.fac.mapper.RepairOrderMapper;
import com.fac.mapper.UsersMapper;
import com.fac.result.PageResult;
import com.fac.service.RepairOrderService;
import com.fac.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 维修订单服务实现类
 */
@Service
@Slf4j
public class RepairOrderServiceImpl implements RepairOrderService {

    @Autowired
    private RepairOrderMapper repairOrderMapper;

    @Autowired
    private EquipmentMapper equipmentMapper;

    @Autowired
    private UsersMapper usersMapper;

    /**
     * 创建维修订单
     */
    @Override
    @Transactional
    public RepairOrderCreateVO create(RepairOrderCreateDTO createDTO) {
        // 查询设备信息
        Equipment equipment = equipmentMapper.selectById(createDTO.getEquipmentId());
        if (equipment == null) {
            throw new BusinessException(ExceptionConstant.EQUIPMENT_NOT_FOUND);
        }

        // 生成订单编号
        String orderCode = generateOrderCode();

        // 创建订单
        RepairOrder order = RepairOrder.builder()
                .code(orderCode)
                .equipmentId(createDTO.getEquipmentId())
                // TODO: 从当前登录用户获取
                .reportUserId(1L)
                .faultDescription(createDTO.getFaultDescription())
                .status(RepairStatus.PENDING)
                .priority(createDTO.getPriority())
                .build();

        // 保存订单
        repairOrderMapper.insert(order);

        // 更新设备状态为维修中
        equipment.setStatus(EquipmentStatus.REPAIRING);
        equipmentMapper.updateById(equipment);

        // 返回结果
        return RepairOrderCreateVO.builder()
                .orderId(order.getOrderId())
                .code(order.getCode())
                .equipmentName(equipment.getName())
                .status(order.getStatus())
                .build();
    }

    /**
     * 分页查询维修订单
     */
    @Override
    public PageResult pageQuery(RepairOrderPageQueryDTO queryDTO) {
        // 构建查询条件
        LambdaQueryWrapper<RepairOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(queryDTO.getStatus() != null, RepairOrder::getStatus, queryDTO.getStatus())
                .eq(queryDTO.getPriority() != null, RepairOrder::getPriority, queryDTO.getPriority())
                .eq(queryDTO.getEquipmentId() != null, RepairOrder::getEquipmentId, queryDTO.getEquipmentId())
                .orderByDesc(RepairOrder::getCreatedAt);

        // 分页查询
        Page<RepairOrder> page = repairOrderMapper.selectPage(
                new Page<>(queryDTO.getPage(), queryDTO.getSize()),
                wrapper
        );

        // 转换为VO
        List<RepairOrderVO> voList = page.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        return new PageResult(page.getTotal(), voList);
    }

    /**
     * 分配维修工
     */
    @Override
    @Transactional
    public RepairOrderAssignVO assign(Long orderId, RepairOrderAssignDTO assignDTO) {
        // 查询订单
        RepairOrder order = repairOrderMapper.selectById(orderId);
        if (order == null) {
            throw new BusinessException(ExceptionConstant.REPAIR_ORDER_NOT_FOUND);
        }

        // 检查订单状态
        if (order.getStatus() != RepairStatus.PENDING) {
            throw new BusinessException(ExceptionConstant.REPAIR_ORDER_STATUS_ERROR);
        }

        // 查询维修工信息
        Users repairUser = usersMapper.selectById(assignDTO.getRepairUserId());
        if (repairUser == null) {
            throw new BusinessException(ExceptionConstant.REPAIR_WORKER_NOT_FOUND);
        }

        // 更新订单
        order.setRepairUserId(assignDTO.getRepairUserId());
        order.setStatus(RepairStatus.PROCESSING);
        order.setStartTime(LocalDateTime.now());
        repairOrderMapper.updateById(order);

        // 返回结果
        return RepairOrderAssignVO.builder()
                .orderId(order.getOrderId())
                .repairUserName(repairUser.getRealName())
                .status(order.getStatus())
                .build();
    }

    /**
     * 更新维修进度
     */
    @Override
    @Transactional
    public RepairOrderProgressVO updateProgress(Long orderId, RepairOrderProgressDTO progressDTO) {
        // 查询订单
        RepairOrder order = repairOrderMapper.selectById(orderId);
        if (order == null) {
            throw new BusinessException(ExceptionConstant.REPAIR_ORDER_NOT_FOUND);
        }

        // 检查订单状态
        if (order.getStatus() != RepairStatus.PROCESSING) {
            throw new BusinessException(ExceptionConstant.REPAIR_ORDER_STATUS_ERROR);
        }

        // 更新订单
        order.setRepairSolution(progressDTO.getRepairSolution());
        order.setRepairMaterials(progressDTO.getRepairMaterials());
        order.setRepairFee(progressDTO.getRepairFee());
        order.setStatus(progressDTO.getStatus());
        order.setQualityCheckResult(progressDTO.getQualityCheckResult());

        // 如果是完成状态，设置完成时间
        if (progressDTO.getStatus() == RepairStatus.COMPLETED) {
            order.setFinishTime(LocalDateTime.now());

            // 更新设备状态为正常
            Equipment equipment = equipmentMapper.selectById(order.getEquipmentId());
            equipment.setStatus(EquipmentStatus.IDLE);
            equipmentMapper.updateById(equipment);
        }

        repairOrderMapper.updateById(order);

        // 返回结果
        return RepairOrderProgressVO.builder()
                .orderId(order.getOrderId())
                .status(order.getStatus())
                .finishTime(order.getFinishTime())
                .build();
    }

    /**
     * 生成订单编号
     */
    private String generateOrderCode() {
        LocalDateTime now = LocalDateTime.now();
        String date = String.format("%tY%<tm%<td", now);

        // 查询当天最大序号
        String prefix = "R" + date;
        LambdaQueryWrapper<RepairOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.likeRight(RepairOrder::getCode, prefix)
                .orderByDesc(RepairOrder::getCode)
                .last("LIMIT 1");

        RepairOrder lastOrder = repairOrderMapper.selectOne(queryWrapper);

        int sequence = 1;
        if (lastOrder != null) {
            String lastCode = lastOrder.getCode();
            sequence = Integer.parseInt(lastCode.substring(9)) + 1;
        }

        return String.format("%s%03d", prefix, sequence);
    }

    /**
     * 转换为VO
     */
    private RepairOrderVO convertToVO(RepairOrder order) {
        // 查询设备信息
        Equipment equipment = equipmentMapper.selectById(order.getEquipmentId());
        
        // 查询报修人信息
        Users reportUser = usersMapper.selectById(order.getReportUserId());
        
        // 查询维修工信息
        Users repairUser = null;
        if (order.getRepairUserId() != null) {
            repairUser = usersMapper.selectById(order.getRepairUserId());
        }

        return RepairOrderVO.builder()
                .orderId(order.getOrderId())
                .code(order.getCode())
                .equipmentName(equipment != null ? equipment.getName() : null)
                .faultDescription(order.getFaultDescription())
                .reportUserName(reportUser != null ? reportUser.getRealName() : null)
                .repairUserName(repairUser != null ? repairUser.getRealName() : null)
                .priority(order.getPriority())
                .status(order.getStatus())
                .startTime(order.getStartTime())
                .finishTime(order.getFinishTime())
                .build();
    }
} 